home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-08-22 | 64.0 KB | 2,651 lines |
- This is a new archive version of TRN at patchlevel 3.
- The original posting took up Volume23, issues 60 to 73, with
- various problems. These files replace those issues.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: head.c mt-read.c rcln.c search.c sw.c
- # Wrapped by rsalz@litchi.bbn.com on Fri Aug 23 16:39:00 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 10 (of 14)."'
- if test -f 'head.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'head.c'\"
- else
- echo shar: Extracting \"'head.c'\" \(9017 characters\)
- sed "s/^X//" >'head.c' <<'END_OF_FILE'
- X/* $Header: head.c,v 4.3.3.2 91/01/16 02:41:15 davison Trn $
- X *
- X * $Log: head.c,v $
- X * Revision 4.3.3.2 91/01/16 02:41:15 davison
- X * Integrated rn patches 48-54.
- X *
- X * Revision 4.3.3.1 90/07/21 20:19:26 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.7 90/11/22 13:49:50 sob
- X * Added changes to make System V compilers happy.
- X *
- X * Revision 4.3.2.6 90/10/01 01:59:10 sob
- X * Fixed possible core dump problem reported by geoff@desint.uucp
- X *
- X * Revision 4.3.2.5 90/03/22 23:04:22 sob
- X * Fixes provided by Wayne Davison <drivax!davison>
- X *
- X * Revision 4.3.2.4 89/11/27 01:30:35 sob
- X * Altered NNTP code per ideas suggested by Bela Lubkin
- X * <filbo@gorn.santa-cruz.ca.us>
- X *
- X * Revision 4.3.2.3 89/11/26 22:53:52 sob
- X * Add new patches to make RRN be faster.
- X *
- X * Revision 4.3.2.2 89/11/08 01:17:46 sob
- X * Added changes to insure that this will compile for RN or RRN with no
- X * changes to the source code.
- X *
- X * Revision 4.3.2.1 89/11/06 00:37:18 sob
- X * Added RRN support from NNTP 1.5
- X *
- X * Revision 4.3.1.2 85/05/10 13:47:25 lwall
- X * Added debugging stuff.
- X *
- X * Revision 4.3.1.1 85/05/10 11:32:30 lwall
- X * Branch for patches.
- X *
- X * Revision 4.3 85/05/01 11:38:21 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "artio.h"
- X#include "bits.h"
- X#ifdef SERVER
- X#include "server.h"
- X#endif
- X#include "util.h"
- X#include "INTERN.h"
- X#include "head.h"
- X
- Xbool first_one; /* is this the 1st occurance of this header line? */
- X
- Xstatic char htypeix[26] =
- X {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- X
- Xvoid
- Xhead_init()
- X{
- X register int i;
- X
- X for (i=HEAD_FIRST+1; i<HEAD_LAST; i++)
- X htypeix[*htype[i].ht_name - 'a'] = i;
- X}
- X
- X#ifdef DEBUGGING
- Xdumpheader(where)
- Xchar *where;
- X{
- X register int i;
- X
- X printf("header: %d %s", parsed_art, where);
- X
- X for (i=0; i<HEAD_LAST; i++) {
- X printf("%15s %4d %4d %03o\n",htype[i].ht_name,
- X htype[i].ht_minpos,
- X htype[i].ht_maxpos,
- X htype[i].ht_flags) FLUSH;
- X }
- X}
- X#endif
- X
- Xint
- Xset_line_type(bufptr,colon)
- Xchar *bufptr;
- Xregister char *colon;
- X{
- X char lc[LONGKEY+3];
- X register char *t, *f;
- X register int i, len;
- X
- X if (colon-bufptr > LONGKEY+2)
- X return SOME_LINE;
- X
- X for (t=lc,f=bufptr; f<colon; f++, t++) {
- X if (isspace(*f))
- X /* guard against space before : */
- X break;
- X *t = isupper(*f) ? tolower(*f) : *f;
- X }
- X *t = '\0';
- X f = lc; /* get lc into register */
- X len = t - f;
- X
- X /* now scan the headtype table, backwards so we don't have to supply an
- X * extra terminating value, using first letter as index, and length as
- X * optimization to avoid calling subroutine strEQ unnecessarily. Hauls.
- X */
- X
- X if (islower(*f)) {
- X for (i = htypeix[*f - 'a']; *htype[i].ht_name == *f; --i) {
- X if (len == htype[i].ht_length && strEQ(f, htype[i].ht_name)) {
- X return i;
- X }
- X }
- X }
- X return SOME_LINE;
- X}
- X
- Xvoid
- Xstart_header(artnum)
- XART_NUM artnum;
- X{
- X register int i;
- X
- X#ifdef DEBUGGING
- X if (debug & 4)
- X dumpheader("start_header\n");
- X#endif
- X for (i=0; i<HEAD_LAST; i++) {
- X htype[i].ht_minpos = -1;
- X htype[i].ht_maxpos = 0;
- X }
- X in_header = SOME_LINE;
- X first_one = FALSE;
- X#ifdef ASYNC_PARSE
- X parsed_art = artnum;
- X#endif
- X}
- X
- Xbool
- Xparseline(art_buf,newhide,oldhide)
- Xchar *art_buf;
- Xint newhide, oldhide;
- X{
- X if (*art_buf == ' ' || *art_buf == '\t')
- X /* header continuation line? */
- X return oldhide;
- X else { /* maybe another header line */
- X char *s;
- X
- X if (first_one) { /* did we just pass 1st occurance? */
- X first_one = FALSE;
- X htype[in_header].ht_maxpos = artpos;
- X /* remember where line left off */
- X }
- X s = index(art_buf,':');
- X if (s == Nullch) {
- X /* is it the end of the header? */
- X htype[PAST_HEADER].ht_minpos =
- X (*art_buf == '\n') ? ftell(artfp) : artpos;
- X /* remember where body starts */
- X in_header = PAST_HEADER;
- X }
- X else { /* it is a new header line */
- X in_header = set_line_type(art_buf,s);
- X first_one = (htype[in_header].ht_minpos < 0);
- X if (first_one)
- X htype[in_header].ht_minpos = artpos;
- X#ifdef DEBUGGING
- X if (debug & 4)
- X dumpheader(art_buf);
- X#endif
- X if (htype[in_header].ht_flags & HT_HIDE)
- X return newhide;
- X }
- X }
- X return FALSE; /* don't hide this line */
- X}
- X
- X#ifdef ASYNC_PARSE
- Xint
- Xparse_maybe(artnum)
- XART_NUM artnum;
- X{
- X char tmpbuf[LBUFLEN];
- X
- X if (parsed_art == artnum)
- X return 0;
- X /* no maybe about it now */
- X#ifdef SERVER
- X if (nntpopen(artnum,GET_HEADER) == Nullfp) {
- X#else
- X if (artopen(artnum) == Nullfp) {
- X#endif
- X return -1;
- X }
- X start_header(artnum);
- X while (in_header) {
- X artpos = ftell(artfp);
- X if (fgets(tmpbuf,LBUFLEN,artfp) == Nullch)
- X break;
- X parseline(tmpbuf,FALSE,FALSE);
- X }
- X in_header = PAST_HEADER;
- X return 0;
- X}
- X#endif
- X
- X/* get the subject line for an article */
- X
- Xchar *
- Xfetchsubj(artnum,current_subject,copy)
- XART_NUM artnum; /* article to get subject from */
- Xbool current_subject; /* is it in a parsed header? */
- Xbool copy; /* do you want it savestr()ed? */
- X{
- X char *s = Nullch, *t;
- X#ifdef SERVER
- X static int xhdr = 1; /* Can we use xhdr command? */
- X int eoo; /* End of server output */
- X char ser_line[256];
- X#endif /* SERVER */
- X
- X#ifdef CACHESUBJ
- X if (!subj_list) {
- X register ART_NUM i;
- X
- X
- X#ifndef lint
- X subj_list =
- X (char**)safemalloc((MEM_SIZE)((OFFSET(lastart)+2)*sizeof(char *)));
- X#endif /* lint */
- X for (i=0; i<=OFFSET(lastart); i++)
- X subj_list[i] = Nullch;
- X }
- X if (!artnum || artnum > lastart)
- X s = nullstr;
- X else
- X s = subj_list[OFFSET(artnum)];
- X#endif
- X if (s == Nullch) {
- X if (current_subject) {
- X s = fetchlines(artnum,SUBJ_LINE);
- X#ifdef CACHESUBJ
- X subj_list[OFFSET(artnum)] = s;
- X#endif
- X }
- X else {
- X s = safemalloc((MEM_SIZE)256);
- X *s = '\0';
- X#ifdef SERVER
- X if (xhdr) {
- X sprintf(ser_line, "XHDR subject %ld", artnum);
- X put_server(ser_line);
- X if (get_server(ser_line, sizeof (ser_line)) >= 0) {
- X if (ser_line[0] == CHAR_FATAL) {
- X xhdr = 0;
- X } else {
- X while (get_server(ser_line, sizeof (ser_line)) >= 0) {
- X if (ser_line[0] == '.')
- X break;
- X else {
- X t = index(ser_line, ' ');
- X if (t++) {
- X strcpy(s, t);
- X if (t = index(s, '\r'))
- X *t = '\0';
- X }
- X }
- X }
- X }
- X } else {
- X fprintf(stderr,
- X "rrn: Unexpected close of server socket.\n");
- X finalize(1);
- X }
- X }
- X
- X if (!xhdr) {
- X sprintf(ser_line, "HEAD %ld", artnum);
- X put_server(ser_line);
- X eoo = 0;
- X if (get_server(ser_line, 256) >= 0 && ser_line[0] == CHAR_OK) {
- X do {
- X if (get_server(s, 256) < 0 || (*s == '.')) {
- X strcpy(s, "Title: \n");
- X eoo = 1;
- X }
- X } while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
- X
- X if (!eoo)
- X while (get_server(ser_line, sizeof (ser_line)) >= 0 &&
- X ser_line[0] != '.');
- X t = index(s,':')+1;
- X while (*t == ' ') t++;
- X strcpy(s, t);
- X }
- X }
- X#else /* not SERVER */
- X if (artopen(artnum) != Nullfp) {
- X do {
- X if (fgets(s,256,artfp) == Nullch)
- X strcpy(s, "Title: \n");
- X } while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
- X
- X s[strlen(s)-1] = '\0';
- X t = index(s,':')+1;
- X while (*t == ' ') t++;
- X strcpy(s, t);
- X }
- X#endif
- X s = saferealloc(s, (MEM_SIZE)strlen(s)+1);
- X#ifdef CACHESUBJ
- X subj_list[OFFSET(artnum)] = s;
- X#endif
- X }
- X }
- X#ifdef CACHESUBJ
- X if (copy) {
- X t = savestr(s);
- X return t;
- X }
- X else
- X return s;
- X#else
- X if (copy)
- X return s;
- X else {
- X safecpy(cmd_buf,s,CBUFLEN); /* hope this is okay--we're */
- X free(s);
- X return cmd_buf; /* really scraping for space here */
- X }
- X#endif
- X}
- X
- X/* get header lines from an article */
- X
- Xchar *
- Xfetchlines(artnum,which_line)
- XART_NUM artnum; /* article to get line from */
- Xint which_line; /* type of line desired */
- X{
- X char *newbuf, *t, tmp_buf[LBUFLEN];
- X register ART_POS curpos;
- X int size;
- X register ART_POS firstpos;
- X register ART_POS lastpos;
- X
- X#ifdef ASYNC_PARSE
- X if (parse_maybe(artnum))
- X artnum = 0;
- X#endif
- X firstpos = htype[which_line].ht_minpos;
- X lastpos = htype[which_line].ht_maxpos;
- X#ifdef SERVER
- X if (!artnum || firstpos < 0 || nntpopen(artnum,GET_HEADER) == Nullfp) {
- X#else
- X if (!artnum || firstpos < 0 || artopen(artnum) == Nullfp) {
- X#endif
- X newbuf = safemalloc((unsigned int)1);
- X *newbuf = '\0';
- X return newbuf;
- X }
- X#ifndef lint
- X size = lastpos - firstpos + 1;
- X#else
- X size = Null(int);
- X#endif /* lint */
- X#ifdef DEBUGGING
- X if (debug && (size < 1 || size > 1000)) {
- X printf("Firstpos = %ld, lastpos = %ld\n",(long)firstpos,(long)lastpos);
- X gets(tmp_buf);
- X }
- X#endif
- X newbuf = safemalloc((unsigned int)size);
- X *newbuf = '\0';
- X fseek(artfp,firstpos,0);
- X for (curpos = firstpos; curpos < lastpos; curpos = ftell(artfp)) {
- X if (fgets(tmp_buf,LBUFLEN,artfp) == Nullch)
- X break;
- X if (*tmp_buf == ' ' || *tmp_buf == '\t')
- X t = tmp_buf;
- X else {
- X t = index(tmp_buf,':');
- X if (t == Nullch)
- X break;
- X t++;
- X }
- X while (*t == ' ' || *t == '\t') t++;
- X safecat(newbuf,t,size);
- X }
- X return newbuf;
- X}
- X
- END_OF_FILE
- if test 9017 -ne `wc -c <'head.c'`; then
- echo shar: \"'head.c'\" unpacked with wrong size!
- fi
- # end of 'head.c'
- fi
- if test -f 'mt-read.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mt-read.c'\"
- else
- echo shar: Extracting \"'mt-read.c'\" \(12741 characters\)
- sed "s/^X//" >'mt-read.c' <<'END_OF_FILE'
- X/* $Header: mt-read.c,v 4.3.3.2 91/01/16 02:49:15 davison Trn $
- X**
- X** $Log: mt-read.c,v $
- X** Revision 4.3.3.2 91/01/16 02:49:15 davison
- X** Changed Free() to safefree(). Tweaked fopen for possible binary open mode.
- X**
- X** Revision 4.3.3.1 90/07/24 23:51:12 davison
- X** Initial Trn Release
- X**
- X*/
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "mthreads.h"
- X
- Xstatic FILE *fp_in;
- X
- Xvoid tweak_roots();
- X
- X/* Attempt to open the thread file. If it's there, only grab the totals
- X** from the start of the file. This should give them enough information
- X** to decide if they need to read the whole thing into memory.
- X*/
- Xint
- Xinit_data( filename )
- Xchar *filename;
- X{
- X root_root = Null(ROOT*);
- X author_root = Null(AUTHOR*);
- X unk_domain.ids = Nullart;
- X unk_domain.link = Null(DOMAIN*);
- X
- X if( (fp_in = fopen( filename, FOPEN_RB )) == Nullfp ) {
- X bzero( &total, sizeof (TOTAL) );
- X return 0;
- X }
- X if( fread( &total, 1, sizeof (TOTAL), fp_in ) < sizeof (TOTAL) ) {
- X fclose( fp_in );
- X bzero( &total, sizeof (TOTAL) );
- X return 0;
- X }
- X return 1;
- X}
- X
- X/* They want everything. Read in the packed information and transform it
- X** into a set of linked structures that is easily manipulated.
- X*/
- Xint
- Xread_data()
- X{
- X if( read_authors()
- X && read_subjects()
- X && read_roots()
- X && read_articles()
- X && read_ids() )
- X {
- X tweak_roots();
- X fclose( fp_in );
- X return 1;
- X }
- X /* Something failed. Safefree takes care of checking if we're partially
- X ** allocated. Any linked-list structures we created were freed before
- X ** we got here.
- X */
- X safefree( &strings );
- X safefree( &subject_cnts );
- X safefree( &author_cnts );
- X safefree( &root_array );
- X safefree( &subject_array );
- X safefree( &article_array );
- X safefree( &ids );
- X fclose( fp_in );
- X return 0;
- X}
- X
- X/* They don't want to read the data. Close the file if we opened it.
- X*/
- Xvoid
- Xdont_read_data( open_flag )
- Xint open_flag; /* 0 == not opened, 1 == open failed, 2 == open */
- X{
- X if( open_flag == 2 ) {
- X fclose( fp_in );
- X }
- X}
- X
- X#define give_string_to( dest ) /* Comment for makedepend to \
- X ** ignore the backslash above */ \
- X{\
- X register MEM_SIZE len = strlen( string_ptr ) + 1;\
- X dest = safemalloc( len );\
- X bcopy( string_ptr, dest, (int)len );\
- X string_ptr += len;\
- X}
- X
- Xchar *subject_strings;
- X
- X/* The author information is an array of use-counts, followed by all the
- X** null-terminated strings crammed together. The subject strings are read
- X** in at the same time, since they are appended to the end of the author
- X** strings.
- X*/
- Xint
- Xread_authors()
- X{
- X register int count;
- X register char *string_ptr;
- X register WORD *authp;
- X register AUTHOR *author, *last_author, **author_ptr;
- X
- X if( !read_item( &author_cnts, (MEM_SIZE)total.author * sizeof (WORD) )
- X || !read_item( &strings, total.string1 ) ) {
- X return 0;
- X }
- X
- X /* We'll use this array to point each article at its proper author
- X ** (packed values are saved as indexes).
- X */
- X author_array = (AUTHOR**)safemalloc( total.author * sizeof (AUTHOR*) );
- X author_ptr = author_array;
- X
- X authp = author_cnts;
- X string_ptr = strings;
- X
- X last_author = Null(AUTHOR*);
- X for( count = total.author; count--; ) {
- X *author_ptr++ = author = (AUTHOR*)safemalloc( sizeof (AUTHOR) );
- X if( !last_author ) {
- X author_root = author;
- X } else {
- X last_author->link = author;
- X }
- X give_string_to( author->name );
- X author->count = *authp++;
- X last_author = author;
- X }
- X last_author->link = Null(AUTHOR*);
- X
- X subject_strings = string_ptr;
- X
- X free( author_cnts );
- X author_cnts = Null(WORD*);
- X
- X return 1;
- X}
- X
- X/* The subject values consist of the crammed-together null-terminated strings
- X** (already read in above) and the use-count array. They were saved in the
- X** order that the roots will need when they are unpacked.
- X*/
- Xint
- Xread_subjects()
- X{
- X if( !read_item( &subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD) ) ) {
- X return 0;
- X }
- X return 1;
- X}
- X
- X/* Read in the packed root structures and recreate the linked list versions,
- X** processing each root's subjects as we go. Defer interpretation of article
- X** offsets until we unpack the article structures.
- X*/
- Xint
- Xread_roots()
- X{
- X register int count;
- X register char *string_ptr;
- X register WORD *subjp;
- X ROOT *root, *last_root, **root_ptr;
- X SUBJECT *subject, *last_subject, **subj_ptr;
- X int ret;
- X
- X /* Use this array when unpacking the article's subject offsets. */
- X subject_array = (SUBJECT**)safemalloc( total.subject * sizeof (SUBJECT*) );
- X subj_ptr = subject_array;
- X /* And this array points the article's root offsets that the right spot. */
- X root_array = (ROOT**)safemalloc( total.root * sizeof (ROOT*) );
- X root_ptr = root_array;
- X
- X subjp = subject_cnts;
- X string_ptr = subject_strings;
- X
- X#ifndef lint
- X last_root = (ROOT*)&root_root;
- X#else
- X last_root = Null(ROOT*);
- X#endif
- X for( count = total.root; count--; ) {
- X ret = fread( &p_root, 1, sizeof (PACKED_ROOT), fp_in );
- X if( ret != sizeof (PACKED_ROOT) ) {
- X log_error( "failed root read -- %d bytes instead of %d.\n",
- X ret, sizeof (PACKED_ROOT) );
- X ret = 0;
- X /* Free the roots we've read so far and their subjects. */
- X while( root_ptr != root_array ) {
- X free( *--root_ptr );
- X }
- X while( subj_ptr != subject_array ) {
- X free( (*--subj_ptr)->str );
- X free( *subj_ptr );
- X }
- X goto finish_up;
- X }
- X *root_ptr++ = root = (ROOT*)safemalloc( sizeof (ROOT) );
- X root->link = Null(ROOT*);
- X root->seq = p_root.articles;
- X root->root_num = p_root.root_num;
- X root->thread_cnt = p_root.thread_cnt;
- X root->subject_cnt = p_root.subject_cnt;
- X last_subject = Null(SUBJECT*);
- X while( p_root.subject_cnt-- ) {
- X *subj_ptr++ = subject = (SUBJECT*)safemalloc( sizeof (SUBJECT) );
- X if( !last_subject ) {
- X root->subjects = subject;
- X } else {
- X last_subject->link = subject;
- X }
- X give_string_to( subject->str );
- X subject->count = *subjp++;
- X last_subject = subject;
- X }
- X last_subject->link = Null(SUBJECT*);
- X last_root->link = root;
- X last_root = root;
- X }
- X ret = 1;
- X
- X finish_up:
- X free( subject_cnts );
- X free( strings );
- X subject_cnts = Null(WORD*);
- X strings = Nullch;
- X
- X return ret;
- X}
- X
- X/* A simple routine that checks the validity of the article's subject value.
- X** A -1 means that it is NULL, otherwise it should be an offset into the
- X** subject array we just unpacked.
- X*/
- XSUBJECT *
- Xvalid_subject( num, art_num )
- XWORD num;
- Xlong art_num;
- X{
- X if( num == -1 ) {
- X return Null(SUBJECT*);
- X }
- X if( num < 0 || num >= total.subject ) {
- X log_error( "Invalid subject in data file: %d [%ld]\n", num, art_num );
- X return Null(SUBJECT*);
- X }
- X return subject_array[num];
- X}
- X
- X/* Ditto for author checking. */
- XAUTHOR *
- Xvalid_author( num, art_num )
- XWORD num;
- Xlong art_num;
- X{
- X if( num == -1 ) {
- X return Null(AUTHOR*);
- X }
- X if( num < 0 || num >= total.author ) {
- X log_error( "Invalid author in data file: %d [%ld]\n", num, art_num );
- X return Null(AUTHOR*);
- X }
- X return author_array[num];
- X}
- X
- X/* Our parent/sibling information is a relative offset in the article array.
- X** zero for none. Child values are always found in the very next array
- X** element if child_cnt is non-zero.
- X*/
- X#define valid_node( rel, num ) (!(rel)? Nullart : article_array[(rel)+(num)])
- X
- X/* Read the articles into their linked lists. Point everything everywhere. */
- Xint
- Xread_articles()
- X{
- X register int count;
- X register ARTICLE *article, **article_ptr;
- X int ret;
- X
- X /* Build an array to interpret interlinkages of articles. */
- X article_array = (ARTICLE**)safemalloc( total.article * sizeof (ARTICLE*) );
- X article_ptr = article_array;
- X
- X /* Allocate all the structures up-front so that we can point to un-read
- X ** siblings as we go.
- X */
- X for( count = total.article; count--; ) {
- X *article_ptr++ = (ARTICLE*)safemalloc( sizeof (ARTICLE) );
- X }
- X article_ptr = article_array;
- X for( count = 0; count < total.article; count++ ) {
- X ret = fread( &p_article, 1, sizeof (PACKED_ARTICLE), fp_in );
- X if( ret != sizeof (PACKED_ARTICLE) ) {
- X log_error( "failed article read -- %d bytes instead of %d.\n", ret, sizeof (PACKED_ARTICLE) );
- X ret = 0;
- X goto finish_up;
- X }
- X article = *article_ptr++;
- X article->num = p_article.num;
- X article->date = p_article.date;
- X article->subject = valid_subject( p_article.subject, p_article.num );
- X article->author = valid_author( p_article.author, p_article.num );
- X article->flags = p_article.flags;
- X article->child_cnt = p_article.child_cnt;
- X article->parent = valid_node( p_article.parent, count );
- X article->children = article->child_cnt?article_array[count+1]:Nullart;
- X article->siblings = valid_node( p_article.siblings, count );
- X article->root = root_array[p_article.root];
- X }
- X ret = 1;
- X
- X finish_up:
- X /* We're done with most of the pointer arrays. */
- X free( root_array );
- X free( subject_array );
- X free( author_array );
- X root_array = Null(ROOT**);
- X subject_array = Null(SUBJECT**);
- X author_array = Null(AUTHOR**);
- X
- X return ret;
- X}
- X
- X/* Read the message-id strings and attach them to each article. The data
- X** format consists of the mushed-together null-terminated strings (a domain
- X** name followed by all its unique-id prefixes) and then the article offsets
- X** to which they belong. The first domain name was omitted, as it is the
- X** ".unknown." domain for those truly weird message-id's without '@'s.
- X*/
- Xint
- Xread_ids()
- X{
- X register DOMAIN *domain, *last;
- X register ARTICLE *article;
- X register char *string_ptr;
- X register int i, count;
- X
- X if( !read_item( &strings, total.string2 ) ) {
- X return 0;
- X }
- X if( !read_item( &ids,
- X (MEM_SIZE)(total.article+total.domain+1) * sizeof (WORD) ) ) {
- X return 0;
- X }
- X string_ptr = strings;
- X
- X last = Null(DOMAIN*);
- X for( i = 0, count = total.domain + 1; count--; i++ ) {
- X if( i ) {
- X domain = (DOMAIN*)safemalloc( sizeof (DOMAIN) );
- X give_string_to( domain->name );
- X } else {
- X domain = &unk_domain;
- X }
- X if( ids[i] == -1 ) {
- X domain->ids = Nullart;
- X } else {
- X article = article_array[ids[i]];
- X domain->ids = article;
- X for( ;; ) {
- X give_string_to( article->id );
- X article->domain = domain;
- X if( ids[++i] != -1 ) {
- X article = article->id_link = article_array[ids[i]];
- X } else {
- X article->id_link = Nullart;
- X break;
- X }
- X }
- X }
- X if( last ) {
- X last->link = domain;
- X }
- X last = domain;
- X }
- X last->link = Null(DOMAIN*);
- X free( ids );
- X free( strings );
- X ids = Null(WORD*);
- X strings = Nullch;
- X
- X return 1;
- X}
- X
- X/* And finally, point all the roots at their root articles and get rid
- X** of anything left over that was used to aid our unpacking.
- X*/
- Xvoid
- Xtweak_roots()
- X{
- X register ROOT *root;
- X
- X for( root = root_root; root; root = root->link ) {
- X root->articles = article_array[root->seq];
- X }
- X free( article_array );
- X article_array = Null(ARTICLE**);
- X}
- X
- X/* A short-hand for reading a chunk of the file into a malloc'ed array.
- X*/
- Xint
- Xread_item( dest, len )
- Xchar **dest;
- XMEM_SIZE len;
- X{
- X int ret;
- X
- X *dest = safemalloc( len );
- X ret = fread( *dest, 1, (int)len, fp_in );
- X if( ret != len ) {
- X log_error( "Only read %ld bytes instead of %ld.\n",
- X (long)ret, (long)len );
- X free( *dest );
- X *dest = Nullch;
- X return 0;
- X }
- X return 1;
- X}
- X
- X/* Interpret rn's '%X' and '%x' path prefixes without including all their
- X** source. Names that don't start with '%' or '/' are prefixed with the
- X** SPOOL directory.
- X*/
- Xchar *
- Xfile_exp( name )
- Xchar *name;
- X{
- X static char name_buff[256];
- X
- X if( *name == '/' ) { /* fully qualified names are left alone */
- X return name;
- X } else if( *name != '%' ) { /* all normal names are relative to SPOOL */
- X sprintf( name_buff, "%s/%s", SPOOL, name );
- X } else { /* interpret %x (LIB) & %X (RNLIB) */
- X if( name[1] == 'x' ) {
- X strcpy( name_buff, LIB );
- X } else if( name[1] == 'X' ) {
- X strcpy( name_buff, RNLIB );
- X } else {
- X log_entry( "Unknown expansion: %s", name );
- X exit( 1 );
- X }
- X strcat( name_buff, name+2 );
- X }
- X return name_buff;
- X}
- X
- X#ifndef lint
- X/* A malloc that bombs-out when memory is exhausted. */
- Xchar *
- Xsafemalloc( amount )
- XMEM_SIZE amount;
- X{
- X register char *cp;
- X extern char *malloc();
- X
- X if( (cp = malloc( amount )) == Nullch ) {
- X log_error( "malloc(%ld) failed.\n", (long)amount );
- X exit( 1 );
- X }
- X return cp;
- X}
- X#endif
- X
- X/* Create a malloc'ed copy of a string. */
- Xchar *
- Xsavestr( str )
- Xchar *str;
- X{
- X register MEM_SIZE len = strlen( str ) + 1;
- X register char *newaddr = safemalloc( len );
- X
- X bcopy( str, newaddr, (int)len );
- X
- X return newaddr;
- X}
- X
- X#ifndef lint
- X/* Free some memory if it hasn't already been freed. */
- Xvoid
- Xsafefree( pp )
- Xchar **pp;
- X{
- X if( *pp ) {
- X free( *pp );
- X *pp = Nullch;
- X }
- X}
- X#endif
- END_OF_FILE
- if test 12741 -ne `wc -c <'mt-read.c'`; then
- echo shar: \"'mt-read.c'\" unpacked with wrong size!
- fi
- # end of 'mt-read.c'
- fi
- if test -f 'rcln.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rcln.c'\"
- else
- echo shar: Extracting \"'rcln.c'\" \(13006 characters\)
- sed "s/^X//" >'rcln.c' <<'END_OF_FILE'
- X/* $Header: rcln.c,v 4.3.3.2 90/08/20 16:46:05 davison Trn $
- X *
- X * $Log: rcln.c,v $
- X * Revision 4.3.3.2 90/08/20 16:46:05 davison
- X * Removed extraneous xref boundary check.
- X *
- X * Revision 4.3.3.1 90/06/20 22:39:19 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.1 90/04/23 00:22:22 sob
- X * Changed atoi to atol and fixed RCS information.
- X *
- X * Revision 4.3.1.2 85/07/23 17:39:08 lwall
- X * Oops, was freeing a static buf on -c in checkexpired.
- X *
- X * Revision 4.3.1.1 85/05/10 11:37:08 lwall
- X * Branch for patches.
- X *
- X * Revision 4.3 85/05/01 11:45:36 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "util.h"
- X#include "rcstuff.h"
- X#include "ngdata.h"
- X#include "INTERN.h"
- X#include "rcln.h"
- X
- Xvoid
- Xrcln_init()
- X{
- X ;
- X}
- X
- X#ifdef CATCHUP
- Xvoid
- Xcatch_up(ngx)
- XNG_NUM ngx;
- X{
- X char tmpbuf[128];
- X char *tmpp;
- X
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\nMarking %s as all read.\n",rcline[ngx]) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X fputs("\nMarked read\n",stdout) FLUSH;
- X#endif
- X sprintf(tmpbuf,"%s: 1-%ld", rcline[ngx],(long)getngsize(ngx));
- X free(rcline[ngx]);
- X rcline[ngx] = savestr(tmpbuf);
- X tmpp = rcline[ngx] + rcnums[ngx] - 1;
- X *tmpp = '\0';
- X write_rc();
- X}
- X#endif
- X
- X/* add an article number to a newsgroup, if it isn't already read */
- X
- Xint
- Xaddartnum(artnum,ngnam)
- XART_NUM artnum;
- Xchar *ngnam;
- X{
- X register NG_NUM ngnum = find_ng(ngnam);
- X register char *s, *t, *maxt = Nullch;
- X ART_NUM min = 0, max = -1, lastnum = 0;
- X char *mbuf;
- X bool morenum;
- X
- X if (!artnum)
- X return 0;
- X if (ngnum == nextrcline || !rcnums[ngnum])
- X /* not found in newsrc? */
- X return 0;
- X#ifdef CACHEFIRST
- X if (!abs1st[ngnum])
- X#else
- X if (!toread[ngnum])
- X#endif
- X /* now is a good time to trim down */
- X set_toread(ngnum); /* the list due to expires if we */
- X /* have not yet. */
- X#if defined(DEBUGGING) && !defined(USETHREADS)
- X if (artnum > ngmax[ngnum] + 10 /* allow for incoming articles */
- X ) {
- X printf("\nCorrupt Xref line!!! %ld --> %s(1..%ld)\n",
- X artnum,ngnam,
- X ngmax[ngnum]) FLUSH;
- X paranoid = TRUE; /* paranoia reigns supreme */
- X return -1; /* hope this was the first newsgroup */
- X }
- X#endif
- X
- X if (toread[ngnum] == TR_BOGUS)
- X return 0;
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%ld->\n%s%c%s\n",(long)artnum,rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X s = rcline[ngnum] + rcnums[ngnum];
- X while (*s == ' ') s++; /* skip spaces */
- X t = s;
- X while (isdigit(*s) && artnum >= (min = atol(s))) {
- X /* while it might have been read */
- X for (t = s; isdigit(*t); t++) ; /* skip number */
- X if (*t == '-') { /* is it a range? */
- X t++; /* skip to next number */
- X if (artnum <= (max = atol(t)))
- X return 0; /* it is in range => already read */
- X lastnum = max; /* remember it */
- X maxt = t; /* remember position in case we */
- X /* want to overwrite the max */
- X while (isdigit(*t)) t++; /* skip second number */
- X }
- X else {
- X if (artnum == min) /* explicitly a read article? */
- X return 0;
- X lastnum = min; /* remember what the number was */
- X maxt = Nullch; /* last one was not a range */
- X }
- X while (*t && !isdigit(*t)) t++; /* skip comma and any spaces */
- X s = t;
- X }
- X
- X /* we have not read it, so insert the article number before s */
- X
- X morenum = isdigit(*s); /* will it need a comma after? */
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = rcchar[ngnum];
- X mbuf = safemalloc((MEM_SIZE)(strlen(s) + (s-rcline[ngnum]) + 8));
- X strcpy(mbuf,rcline[ngnum]); /* make new rc line */
- X if (maxt && lastnum && artnum == lastnum+1)
- X /* can we just extend last range? */
- X t = mbuf + (maxt-rcline[ngnum]);/* then overwrite previous max */
- X else {
- X t = mbuf + (t-rcline[ngnum]); /* point t into new line instead */
- X if (lastnum) { /* have we parsed any line? */
- X if (!morenum) /* are we adding to the tail? */
- X *t++ = ','; /* supply comma before */
- X if (!maxt && artnum == lastnum+1 && *(t-1) == ',')
- X /* adjacent singletons? */
- X *(t-1) = '-'; /* turn them into a range */
- X }
- X }
- X if (morenum) { /* is there more to life? */
- X if (min == artnum+1) { /* can we consolidate further? */
- X bool range_before = (*(t-1) == '-');
- X bool range_after;
- X char *nextmax;
- X
- X for (nextmax = s; isdigit(*nextmax); nextmax++) ;
- X range_after = *nextmax++ == '-';
- X
- X if (range_before)
- X *t = '\0'; /* artnum is redundant */
- X else
- X sprintf(t,"%ld-",(long)artnum);/* artnum will be new min */
- X
- X if (range_after)
- X s = nextmax; /* *s is redundant */
- X /* else
- X s = s */ /* *s is new max */
- X }
- X else
- X sprintf(t,"%ld,",(long)artnum); /* put the number and comma */
- X }
- X else
- X sprintf(t,"%ld",(long)artnum); /* put the number there (wherever) */
- X strcat(t,s); /* copy remainder of line */
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%s\n",mbuf) FLUSH;
- X }
- X#endif
- X free(rcline[ngnum]);
- X rcline[ngnum] = mbuf; /* pull the switcheroo */
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = '\0';
- X /* wipe out : or ! */
- X if (toread[ngnum] > TR_NONE) /* lest we turn unsub into bogus */
- X --toread[ngnum];
- X return 0;
- X}
- X
- X#ifdef MCHASE
- X/* delete an article number from a newsgroup, if it is there */
- X
- Xvoid
- Xsubartnum(artnum,ngnam)
- Xregister ART_NUM artnum;
- Xchar *ngnam;
- X{
- X register NG_NUM ngnum = find_ng(ngnam);
- X register char *s, *t;
- X register ART_NUM min, max;
- X char *mbuf;
- X int curlen;
- X
- X if (!artnum)
- X return;
- X if (ngnum == nextrcline || !rcnums[ngnum])
- X return; /* not found in newsrc? */
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%ld<-\n%s%c%s\n",(long)artnum,rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X s = rcline[ngnum] + rcnums[ngnum];
- X while (*s == ' ') s++; /* skip spaces */
- X
- X /* a little optimization, since it is almost always the last number */
- X
- X for (t=s; *t; t++) ; /* find end of string */
- X curlen = t-rcline[ngnum];
- X for (t--; isdigit(*t); t--) ; /* find previous delim */
- X if (*t == ',' && atol(t+1) == artnum) {
- X *t = '\0';
- X if (toread[ngnum] >= TR_NONE)
- X ++toread[ngnum];
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER)
- X printf("%s%c %s\n",rcline[ngnum],rcchar[ngnum],s) FLUSH;
- X#endif
- X return;
- X }
- X
- X /* not the last number, oh well, we may need the length anyway */
- X
- X while (isdigit(*s) && artnum >= (min = atol(s))) {
- X /* while it might have been read */
- X for (t = s; isdigit(*t); t++) ; /* skip number */
- X if (*t == '-') { /* is it a range? */
- X t++; /* skip to next number */
- X max = atol(t);
- X while (isdigit(*t)) t++; /* skip second number */
- X if (artnum <= max) {
- X /* it is in range => already read */
- X if (artnum == min) {
- X min++;
- X artnum = 0;
- X }
- X else if (artnum == max) {
- X max--;
- X artnum = 0;
- X }
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = rcchar[ngnum];
- X mbuf = safemalloc((MEM_SIZE)(curlen + (artnum?15:2)));
- X *s = '\0';
- X strcpy(mbuf,rcline[ngnum]); /* make new rc line */
- X s = mbuf + (s-rcline[ngnum]);
- X /* point s into mbuf now */
- X if (artnum) { /* split into two ranges? */
- X prange(s,min,artnum-1);
- X s += strlen(s);
- X *s++ = ',';
- X prange(s,artnum+1,max);
- X }
- X else /* only one range */
- X prange(s,min,max);
- X s += strlen(s);
- X strcpy(s,t); /* copy remainder over */
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%s\n",mbuf) FLUSH;
- X }
- X#endif
- X free(rcline[ngnum]);
- X rcline[ngnum] = mbuf; /* pull the switcheroo */
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = '\0';
- X /* wipe out : or ! */
- X if (toread[ngnum] >= TR_NONE)
- X ++toread[ngnum];
- X return;
- X }
- X }
- X else {
- X if (artnum == min) { /* explicitly a read article? */
- X if (*t == ',') /* pick a comma, any comma */
- X t++;
- X else if (s[-1] == ',')
- X s--;
- X else if (s[-2] == ',') /* (in case of space) */
- X s -= 2;
- X strcpy(s,t); /* no need to realloc */
- X if (toread[ngnum] >= TR_NONE)
- X ++toread[ngnum];
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%s%c%s\n",rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X return;
- X }
- X }
- X while (*t && !isdigit(*t)) t++; /* skip comma and any spaces */
- X s = t;
- X }
- X}
- X
- Xvoid
- Xprange(where,min,max)
- Xchar *where;
- XART_NUM min,max;
- X{
- X if (min == max)
- X sprintf(where,"%ld",(long)min);
- X else
- X sprintf(where,"%ld-%ld",(long)min,(long)max);
- X}
- X#endif
- X
- X/* calculate the number of unread articles for a newsgroup */
- X
- Xvoid
- Xset_toread(ngnum)
- Xregister NG_NUM ngnum;
- X{
- X register char *s, *c, *h;
- X char tmpbuf[64], *mybuf = tmpbuf;
- X char *nums;
- X int length;
- X#ifdef CACHEFIRST
- X bool virgin_ng = (!abs1st[ngnum]);
- X#endif
- X ART_NUM ngsize = getngsize(ngnum);
- X ART_NUM unread = ngsize;
- X ART_NUM newmax;
- X
- X#if defined(DEBUGGING) && !defined(USETHREADS)
- X ngmax[ngnum] = ngsize; /* for checking out-of-range Xrefs */
- X#endif
- X if (ngsize == TR_BOGUS) {
- X printf("Warning! Bogus newsgroup: %s\n",rcline[ngnum]) FLUSH;
- X paranoid = TRUE;
- X toread[ngnum] = TR_BOGUS;
- X return;
- X }
- X#ifdef CACHEFIRST
- X if (virgin_ng)
- X#else
- X if (!toread[ngnum])
- X#endif
- X {
- X sprintf(tmpbuf," 1-%ld",(long)ngsize);
- X if (strNE(tmpbuf,rcline[ngnum]+rcnums[ngnum]))
- X checkexpired(ngnum,ngsize); /* this might realloc rcline */
- X }
- X nums = rcline[ngnum]+rcnums[ngnum];
- X length = strlen(nums);
- X if (length >= 60)
- X mybuf = safemalloc((MEM_SIZE)(length+5));
- X strcpy(mybuf,nums);
- X mybuf[length++] = ',';
- X mybuf[length] = '\0';
- X for (s = mybuf; isspace(*s); s++)
- X ;
- X for ( ; (c = index(s,',')) != Nullch ; s = ++c) {
- X /* for each range */
- X *c = '\0'; /* keep index from running off */
- X if ((h = index(s,'-')) != Nullch) /* find - in range, if any */
- X unread -= (newmax = atol(h+1)) - atol(s) + 1;
- X else if (newmax = atol(s))
- X unread--; /* recalculate length */
- X if (newmax > ngsize) { /* paranoia check */
- X unread = -1;
- X break;
- X }
- X }
- X if (unread >= 0) /* reasonable number? */
- X toread[ngnum] = (ART_UNREAD)unread;
- X /* remember how many are left */
- X#ifdef USETHREADS
- X else if (unread >= -100) {
- X /* If mthreads is in the process of updating the database, it's possible
- X ** for the .thread file to be more up-to-date than the numbers in the
- X ** active file (caused by buffering). If so, it's also possible for the
- X ** user to have read past the end of the group as we know it. Assume
- X ** 100 articles is enough of a buffer to distinguish reset newsgroups.
- X */
- X toread[ngnum] = 0;
- X }
- X#endif
- X else { /* SOMEONE RESET THE NEWSGROUP!!! */
- X toread[ngnum] = (ART_UNREAD)ngsize;
- X /* assume nothing carried over */
- X printf("Warning! Somebody reset %s--assuming nothing read.\n",
- X rcline[ngnum]) FLUSH;
- X *(rcline[ngnum] + rcnums[ngnum]) = '\0';
- X paranoid = TRUE; /* enough to make a guy paranoid */
- X }
- X if (mybuf != tmpbuf)
- X free(mybuf);
- X if (rcchar[ngnum] == NEGCHAR)
- X toread[ngnum] = TR_UNSUB;
- X}
- X
- X/* make sure expired articles are marked as read */
- X
- Xvoid
- Xcheckexpired(ngnum,ngsize)
- Xregister NG_NUM ngnum;
- XART_NUM ngsize;
- X{
- X register ART_NUM a1st = getabsfirst(ngnum,ngsize);
- X register char *s, *t;
- X register ART_NUM num, lastnum = 0;
- X char *mbuf, *newnum;
- X
- X if (a1st<=1)
- X return;
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("1-%ld->\n%s%c%s\n",(long)(a1st-1),rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X for (s = rcline[ngnum] + rcnums[ngnum]; isspace(*s); s++);
- X while (*s && (num = atol(s)) <= a1st) {
- X while (isdigit(*s)) s++;
- X while (*s && !isdigit(*s)) s++;
- X lastnum = num;
- X }
- X if (*s) {
- X if (s[-1] == '-') { /* landed in a range? */
- X if (lastnum != 1) {
- X if (3 + strlen(s) > strlen(rcline[ngnum]+rcnums[ngnum])) {
- X mbuf = safemalloc((MEM_SIZE)(rcnums[ngnum] + 3 +
- X strlen(s) + 1));
- X strcpy(mbuf, rcline[ngnum]);
- X sprintf(mbuf+rcnums[ngnum]," 1-%s",s);
- X free(rcline[ngnum]);
- X rcline[ngnum] = mbuf;
- X } else {
- X sprintf(rcline[ngnum]+rcnums[ngnum]," 1-%s",s);
- X }
- X }
- X goto ret;
- X }
- X }
- X /* s now points to what should follow first range */
- X if (s - rcline[ngnum] > rcnums[ngnum] + 10)
- X mbuf = rcline[ngnum];
- X else {
- X mbuf = safemalloc((MEM_SIZE)(rcnums[ngnum] + strlen(s) + 10));
- X strcpy(mbuf,rcline[ngnum]);
- X }
- X newnum = t = mbuf+rcnums[ngnum];
- X sprintf(t," 1-%ld",(long)(a1st - (lastnum != a1st)));
- X if (*s) {
- X t += strlen(t);
- X *t++ = ',';
- X strcpy(t,s);
- X }
- X if (!checkflag && mbuf == rcline[ngnum]) {
- X rcline[ngnum] = saferealloc(rcline[ngnum],
- X (MEM_SIZE)(rcnums[ngnum] + strlen(newnum) + 1));
- X }
- X else {
- X if (!checkflag)
- X free(rcline[ngnum]);
- X rcline[ngnum] = mbuf;
- X }
- X
- Xret:; /* semicolon in case DEBUGGING undefined */
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%s%c%s\n",rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X}
- X
- END_OF_FILE
- if test 13006 -ne `wc -c <'rcln.c'`; then
- echo shar: \"'rcln.c'\" unpacked with wrong size!
- fi
- # end of 'rcln.c'
- fi
- if test -f 'search.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'search.c'\"
- else
- echo shar: Extracting \"'search.c'\" \(13460 characters\)
- sed "s/^X//" >'search.c' <<'END_OF_FILE'
- X/* $Header: search.c,v 4.3.2.2 90/03/22 23:05:31 sob Exp $
- X *
- X * $Log: search.c,v $
- X * Revision 4.3.2.2 90/03/22 23:05:31 sob
- X * Fixes provided by Wayne Davison <drivax!davison>
- X *
- X * Revision 4.3.2.1 90/03/17 17:46:29 sob
- X * Added changes to insure that null search strings won't result in core dumps
- X * on non-VAX computers.
- X *
- X * Revision 4.3 85/05/01 11:50:16 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X/* string search routines */
- X
- X/* Copyright (c) 1981,1980 James Gosling */
- X
- X/* Modified Aug. 12, 1981 by Tom London to include regular expressions
- X as in ed. RE stuff hacked over by jag to correct a few major problems,
- X mainly dealing with searching within the buffer rather than copying
- X each line to a separate array. Newlines can now appear in RE's */
- X
- X/* Ripped to shreds and glued back together to make a search package,
- X * July 6, 1984, by Larry Wall. (If it doesn't work, it's probably my fault.)
- X * Changes include:
- X * Buffer, window, and mlisp stuff gone.
- X * Translation tables reduced to 1 table.
- X * Expression buffer is now dynamically allocated.
- X * Character classes now implemented with a bitmap.
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "util.h"
- X#include "INTERN.h"
- X#include "search.h"
- X
- X#ifndef BITSPERBYTE
- X#define BITSPERBYTE 8
- X#endif
- X
- X#define BMAPSIZ (127 / BITSPERBYTE + 1)
- X
- X/* meta characters in the "compiled" form of a regular expression */
- X#define CBRA 2 /* \( -- begin bracket */
- X#define CCHR 4 /* a vanilla character */
- X#define CDOT 6 /* . -- match anything except a newline */
- X#define CCL 8 /* [...] -- character class */
- X#define NCCL 10 /* [^...] -- negated character class */
- X#define CDOL 12 /* $ -- matches the end of a line */
- X#define CEND 14 /* The end of the pattern */
- X#define CKET 16 /* \) -- close bracket */
- X#define CBACK 18 /* \N -- backreference to the Nth bracketed
- X string */
- X#define CIRC 20 /* ^ matches the beginning of a line */
- X
- X#define WORD 32 /* matches word character \w */
- X#define NWORD 34 /* matches non-word characer \W */
- X#define WBOUND 36 /* matches word boundary \b */
- X#define NWBOUND 38 /* matches non-(word boundary) \B */
- X
- X#define STAR 01 /* * -- Kleene star, repeats the previous
- X REas many times as possible; the value
- X ORs with the other operator types */
- X
- X#define ASCSIZ 0200
- Xtypedef char TRANSTABLE[ASCSIZ];
- X
- Xstatic TRANSTABLE trans = {
- X0000,0001,0002,0003,0004,0005,0006,0007,
- X0010,0011,0012,0013,0014,0015,0016,0017,
- X0020,0021,0022,0023,0024,0025,0026,0027,
- X0030,0031,0032,0033,0034,0035,0036,0037,
- X0040,0041,0042,0043,0044,0045,0046,0047,
- X0050,0051,0052,0053,0054,0055,0056,0057,
- X0060,0061,0062,0063,0064,0065,0066,0067,
- X0070,0071,0072,0073,0074,0075,0076,0077,
- X0100,0101,0102,0103,0104,0105,0106,0107,
- X0110,0111,0112,0113,0114,0115,0116,0117,
- X0120,0121,0122,0123,0124,0125,0126,0127,
- X0130,0131,0132,0133,0134,0135,0136,0137,
- X0140,0141,0142,0143,0144,0145,0146,0147,
- X0150,0151,0152,0153,0154,0155,0156,0157,
- X0160,0161,0162,0163,0164,0165,0166,0167,
- X0170,0171,0172,0173,0174,0175,0176,0177,
- X};
- Xstatic bool folding = FALSE;
- X
- Xstatic int err;
- Xstatic char *FirstCharacter;
- X
- Xvoid
- Xsearch_init()
- X{
- X#ifdef UNDEF
- X register int i;
- X
- X for (i = 0; i < ASCSIZ; i++)
- X trans[i] = i;
- X#else
- X ;
- X#endif
- X}
- X
- Xvoid
- Xinit_compex(compex)
- Xregister COMPEX *compex;
- X{
- X /* the following must start off zeroed */
- X
- X compex->eblen = 0;
- X compex->brastr = Nullch;
- X}
- X
- Xvoid
- Xfree_compex(compex)
- Xregister COMPEX *compex;
- X{
- X if (compex->eblen) {
- X free(compex->expbuf);
- X compex->eblen = 0;
- X }
- X if (compex->brastr) {
- X free(compex->brastr);
- X compex->brastr = Nullch;
- X }
- X}
- X
- Xstatic char *gbr_str = Nullch;
- Xstatic int gbr_siz = 0;
- X
- Xchar *
- Xgetbracket(compex,n)
- Xregister COMPEX *compex;
- Xint n;
- X{
- X int length = compex->braelist[n] - compex->braslist[n];
- X
- X if (!compex->nbra || n > compex->nbra || !compex->braelist[n] || length<0)
- X return nullstr;
- X growstr(&gbr_str, &gbr_siz, length+1);
- X safecpy(gbr_str, compex->braslist[n], length+1);
- X return gbr_str;
- X}
- X
- Xvoid
- Xcase_fold(which)
- Xint which;
- X{
- X register int i;
- X
- X if (which != folding) {
- X if (which) {
- X for (i = 'A'; i <= 'Z'; i++)
- X trans[i] = tolower(i);
- X }
- X else {
- X for (i = 'A'; i <= 'Z'; i++)
- X trans[i] = i;
- X }
- X folding = which;
- X }
- X}
- X
- X/* Compile the given regular expression into a [secret] internal format */
- X
- Xchar *
- Xcompile (compex, strp, RE, fold)
- Xregister COMPEX *compex;
- Xregister char *strp;
- Xint RE;
- Xint fold;
- X{
- X register int c;
- X register char *ep;
- X char *lastep;
- X char bracket[NBRA],
- X *bracketp;
- X char **alt = compex->alternatives;
- X char *retmes = "Badly formed search string";
- X
- X case_fold(compex->do_folding = fold);
- X if (!compex->eblen) {
- X compex->expbuf = safemalloc(84);
- X compex->eblen = 80;
- X }
- X ep = compex->expbuf; /* point at expression buffer */
- X *alt++ = ep; /* first alternative starts here */
- X bracketp = bracket; /* first bracket goes here */
- X if (*strp == 0) { /* nothing to compile? */
- X if (*ep == 0) /* nothing there yet? */
- X return "Null search string";
- X return Nullch; /* just keep old expression */
- X }
- X compex->nbra = 0; /* no brackets yet */
- X lastep = 0;
- X for (;;) {
- X if (ep - compex->expbuf >= compex->eblen)
- X grow_eb(compex);
- X c = *strp++; /* fetch next char of pattern */
- X if (c == 0) { /* end of pattern? */
- X if (bracketp != bracket) { /* balanced brackets? */
- X#ifdef VERBOSE
- X retmes = "Unbalanced parens";
- X#endif
- X goto cerror;
- X }
- X *ep++ = CEND; /* terminate expression */
- X *alt++ = 0; /* terminal alternative list */
- X /*
- X compex->eblen = ep - compex->expbuf + 1;
- X compex->expbuf = saferealloc(compex->expbuf,compex->eblen+4); */
- X return Nullch; /* return success */
- X }
- X if (c != '*')
- X lastep = ep;
- X if (!RE) { /* just a normal search string? */
- X *ep++ = CCHR; /* everything is a normal char */
- X *ep++ = c;
- X }
- X else /* it is a regular expression */
- X switch (c) {
- X
- X case '\\': /* meta something */
- X switch (c = *strp++) {
- X case '(':
- X if (compex->nbra >= NBRA) {
- X#ifdef VERBOSE
- X retmes = "Too many parens";
- X#endif
- X goto cerror;
- X }
- X *bracketp++ = ++compex->nbra;
- X *ep++ = CBRA;
- X *ep++ = compex->nbra;
- X break;
- X case '|':
- X if (bracketp>bracket) {
- X#ifdef VERBOSE
- X retmes = "No \\| in parens"; /* Alas! */
- X#endif
- X goto cerror;
- X }
- X *ep++ = CEND;
- X *alt++ = ep;
- X break;
- X case ')':
- X if (bracketp <= bracket) {
- X#ifdef VERBOSE
- X retmes = "Unmatched right paren";
- X#endif
- X goto cerror;
- X }
- X *ep++ = CKET;
- X *ep++ = *--bracketp;
- X break;
- X case 'w':
- X *ep++ = WORD;
- X break;
- X case 'W':
- X *ep++ = NWORD;
- X break;
- X case 'b':
- X *ep++ = WBOUND;
- X break;
- X case 'B':
- X *ep++ = NWBOUND;
- X break;
- X case '0': case '1': case '2': case '3': case '4':
- X case '5': case '6': case '7': case '8': case '9':
- X *ep++ = CBACK;
- X *ep++ = c - '0';
- X break;
- X default:
- X *ep++ = CCHR;
- X if (c == '\0')
- X goto cerror;
- X *ep++ = c;
- X break;
- X }
- X break;
- X case '.':
- X *ep++ = CDOT;
- X continue;
- X
- X case '*':
- X if (lastep == 0 || *lastep == CBRA || *lastep == CKET
- X || *lastep == CIRC
- X || (*lastep&STAR)|| *lastep>NWORD)
- X goto defchar;
- X *lastep |= STAR;
- X continue;
- X
- X case '^':
- X if (ep != compex->expbuf && ep[-1] != CEND)
- X goto defchar;
- X *ep++ = CIRC;
- X continue;
- X
- X case '$':
- X if (*strp != 0 && (*strp != '\\' || strp[1] != '|'))
- X goto defchar;
- X *ep++ = CDOL;
- X continue;
- X
- X case '[': { /* character class */
- X register int i;
- X
- X if (ep - compex->expbuf >= compex->eblen - BMAPSIZ)
- X grow_eb(compex); /* reserve bitmap */
- X for (i = BMAPSIZ; i; --i)
- X ep[i] = 0;
- X
- X if ((c = *strp++) == '^') {
- X c = *strp++;
- X *ep++ = NCCL; /* negated */
- X }
- X else
- X *ep++ = CCL; /* normal */
- X
- X i = 0; /* remember oldchar */
- X do {
- X if (c == '\0') {
- X#ifdef VERBOSE
- X retmes = "Missing ]";
- X#endif
- X goto cerror;
- X }
- X if (*strp == '-' && *(++strp))
- X i = *strp++;
- X else
- X i = c;
- X while (c <= i) {
- X ep[c / BITSPERBYTE] |= 1 << (c % BITSPERBYTE);
- X if (fold && isalpha(c))
- X ep[(c ^ 32) / BITSPERBYTE] |=
- X 1 << ((c ^ 32) % BITSPERBYTE);
- X /* set the other bit too */
- X c++;
- X }
- X } while ((c = *strp++) != ']');
- X ep += BMAPSIZ;
- X continue;
- X }
- X
- X defchar:
- X default:
- X *ep++ = CCHR;
- X *ep++ = c;
- X }
- X }
- Xcerror:
- X compex->expbuf[0] = 0;
- X compex->nbra = 0;
- X return retmes;
- X}
- X
- Xvoid
- Xgrow_eb(compex)
- Xregister COMPEX *compex;
- X{
- X compex->eblen += 80;
- X compex->expbuf = saferealloc(compex->expbuf, (MEM_SIZE)compex->eblen + 4);
- X}
- X
- Xchar *
- Xexecute (compex, addr)
- Xregister COMPEX *compex;
- Xchar *addr;
- X{
- X register char *p1 = addr;
- X register char *trt = trans;
- X register int c;
- X
- X if (addr == Nullch || compex->expbuf == Nullch)
- X return Nullch;
- X if (compex->nbra) { /* any brackets? */
- X for (c = 0; c <= compex->nbra; c++)
- X compex->braslist[c] = compex->braelist[c] = Nullch;
- X if (compex->brastr)
- X free(compex->brastr);
- X compex->brastr = savestr(p1); /* in case p1 is not static */
- X p1 = compex->brastr; /* ! */
- X }
- X case_fold(compex->do_folding); /* make sure table is correct */
- X FirstCharacter = p1; /* for ^ tests */
- X if (compex->expbuf[0] == CCHR && !compex->alternatives[1]) {
- X c = trt[compex->expbuf[1]]; /* fast check for first character */
- X do {
- X if (trt[*p1] == c && advance (compex, p1, compex->expbuf))
- X return p1;
- X p1++;
- X } while (*p1 && !err);
- X return Nullch;
- X }
- X else { /* regular algorithm */
- X do {
- X register char **alt = compex->alternatives;
- X while (*alt) {
- X if (advance (compex, p1, *alt++))
- X return p1;
- X }
- X p1++;
- X } while (*p1 && !err);
- X return Nullch;
- X }
- X}
- X
- X/* advance the match of the regular expression starting at ep along the
- X string lp, simulates an NDFSA */
- Xbool
- Xadvance (compex, lp, ep)
- Xregister COMPEX *compex;
- Xregister char *ep;
- Xregister char *lp;
- X{
- X register char *curlp;
- X register char *trt = trans;
- X register int i;
- X
- X while ((*ep & STAR) || *lp || *ep == CIRC || *ep == CKET)
- X switch (*ep++) {
- X
- X case CCHR:
- X if (trt[*ep++] != trt[*lp]) return FALSE;
- X lp++;
- X continue;
- X
- X case CDOT:
- X if (*lp == '\n') return FALSE;
- X lp++;
- X continue;
- X
- X case CDOL:
- X if (!*lp || *lp == '\n')
- X continue;
- X return FALSE;
- X
- X case CIRC:
- X if (lp == FirstCharacter || lp[-1]=='\n')
- X continue;
- X return FALSE;
- X
- X case WORD:
- X if (isalnum(*lp)) {
- X lp++;
- X continue;
- X }
- X return FALSE;
- X
- X case NWORD:
- X if (!isalnum(*lp)) {
- X lp++;
- X continue;
- X }
- X return FALSE;
- X
- X case WBOUND:
- X if ((lp == FirstCharacter || !isalnum(lp[-1])) !=
- X (!*lp || !isalnum(*lp)) )
- X continue;
- X return FALSE;
- X
- X case NWBOUND:
- X if ((lp == FirstCharacter || !isalnum(lp[-1])) ==
- X (!*lp || !isalnum(*lp)))
- X continue;
- X return FALSE;
- X
- X case CEND:
- X return TRUE;
- X
- X case CCL:
- X if (cclass (ep, *lp, 1)) {
- X ep += BMAPSIZ;
- X lp++;
- X continue;
- X }
- X return FALSE;
- X
- X case NCCL:
- X if (cclass (ep, *lp, 0)) {
- X ep += BMAPSIZ;
- X lp++;
- X continue;
- X }
- X return FALSE;
- X
- X case CBRA:
- X compex->braslist[*ep++] = lp;
- X continue;
- X
- X case CKET:
- X i = *ep++;
- X compex->braelist[i] = lp;
- X compex->braelist[0] = lp;
- X compex->braslist[0] = compex->braslist[i];
- X continue;
- X
- X case CBACK:
- X if (compex->braelist[i = *ep++] == 0) {
- X fputs("bad braces\n",stdout) FLUSH;
- X err = TRUE;
- X return FALSE;
- X }
- X if (backref (compex, i, lp)) {
- X lp += compex->braelist[i] - compex->braslist[i];
- X continue;
- X }
- X return FALSE;
- X
- X case CBACK | STAR:
- X if (compex->braelist[i = *ep++] == 0) {
- X fputs("bad braces\n",stdout) FLUSH;
- X err = TRUE;
- X return FALSE;
- X }
- X curlp = lp;
- X while (backref (compex, i, lp)) {
- X lp += compex->braelist[i] - compex->braslist[i];
- X }
- X while (lp >= curlp) {
- X if (advance (compex, lp, ep))
- X return TRUE;
- X lp -= compex->braelist[i] - compex->braslist[i];
- X }
- X continue;
- X
- X case CDOT | STAR:
- X curlp = lp;
- X while (*lp++ && lp[-1] != '\n');
- X goto star;
- X
- X case WORD | STAR:
- X curlp = lp;
- X while (*lp++ && isalnum(lp[-1]));
- X goto star;
- X
- X case NWORD | STAR:
- X curlp = lp;
- X while (*lp++ && !isalnum(lp[-1]));
- X goto star;
- X
- X case CCHR | STAR:
- X curlp = lp;
- X while (*lp++ && trt[lp[-1]] == trt[*ep]);
- X ep++;
- X goto star;
- X
- X case CCL | STAR:
- X case NCCL | STAR:
- X curlp = lp;
- X while (*lp++ && cclass (ep, lp[-1], ep[-1] == (CCL | STAR)));
- X ep += BMAPSIZ;
- X goto star;
- X
- X star:
- X do {
- X lp--;
- X if (advance (compex, lp, ep))
- X return TRUE;
- X } while (lp > curlp);
- X return FALSE;
- X
- X default:
- X fputs("Badly compiled pattern\n",stdout) FLUSH;
- X err = TRUE;
- X return -1;
- X }
- X if (*ep == CEND || *ep == CDOL) {
- X return TRUE;
- X }
- X return FALSE;
- X}
- X
- Xbool
- Xbackref (compex, i, lp)
- Xregister COMPEX *compex;
- Xregister int i;
- Xregister char *lp;
- X{
- X register char *bp;
- X
- X bp = compex->braslist[i];
- X while (*lp && *bp == *lp) {
- X bp++;
- X lp++;
- X if (bp >= compex->braelist[i])
- X return TRUE;
- X }
- X return FALSE;
- X}
- X
- Xbool
- Xcclass (set, c, af)
- Xregister char *set;
- Xregister int c;
- X{
- X c &= 0177;
- X#if BITSPERBYTE == 8
- X if (set[c >> 3] & 1 << (c & 7))
- X#else
- X if (set[c / BITSPERBYTE] & 1 << (c % BITSPERBYTE))
- X#endif
- X return af;
- X return !af;
- X}
- END_OF_FILE
- if test 13460 -ne `wc -c <'search.c'`; then
- echo shar: \"'search.c'\" unpacked with wrong size!
- fi
- # end of 'search.c'
- fi
- if test -f 'sw.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sw.c'\"
- else
- echo shar: Extracting \"'sw.c'\" \(11791 characters\)
- sed "s/^X//" >'sw.c' <<'END_OF_FILE'
- X/* $Header: sw.c,v 4.3.3.2 91/01/16 03:37:38 davison Trn $
- X *
- X * $Log: sw.c,v $
- X * Revision 4.3.3.2 91/01/16 03:37:38 davison
- X * Integrated rn patches 48-54.
- X *
- X * Revision 4.3.3.1 90/06/20 22:40:11 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.4 90/11/22 16:09:19 sob
- X * Added changes to accomodate pickly C preprocessors
- X *
- X * Revision 4.3.2.3 90/05/08 22:06:00 sob
- X * Added quick startup (-q) flag.
- X *
- X * Revision 4.3.2.2 90/03/22 23:05:34 sob
- X * Fixes provided by Wayne Davison <drivax!davison>
- X *
- X * Revision 4.3.2.1 89/12/09 00:52:40 sob
- X * Now handles SIGWINCH correctly.
- X *
- X * Revision 4.3.1.2 85/05/21 13:36:23 lwall
- X * Sped up "rn -c" by not doing unnecessary initialization.
- X *
- X * Revision 4.3.1.1 85/05/10 11:40:38 lwall
- X * Branch for patches.
- X *
- X * Revision 4.3 85/05/01 11:50:54 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "util.h"
- X#include "head.h"
- X#include "only.h"
- X#include "term.h"
- X#include "ng.h"
- X#include "intrp.h"
- X#include "INTERN.h"
- X#include "sw.h"
- X
- Xvoid
- Xsw_init(argc,argv,tcbufptr)
- Xint argc;
- Xchar *argv[];
- Xchar **tcbufptr;
- X{
- X register int i;
- X
- X if (argc >= 2 && strEQ(argv[1],"-c"))
- X checkflag=TRUE; /* so we can optimize for -c */
- X interp(*tcbufptr,1024,GLOBINIT);
- X sw_file(tcbufptr,FALSE);
- X safecpy(*tcbufptr,getenv("RNINIT"),1024);
- X if (**tcbufptr) {
- X if (**tcbufptr == '/') {
- X sw_file(tcbufptr,TRUE);
- X }
- X else
- X sw_list(*tcbufptr);
- X }
- X
- X for (i = 1; i < argc; i++)
- X decode_switch(argv[i]);
- X}
- X
- Xvoid
- Xsw_file(tcbufptr,bleat)
- Xchar **tcbufptr;
- Xbool bleat;
- X{
- X int initfd = open(*tcbufptr,0);
- X
- X if (initfd >= 0) {
- X fstat(initfd,&filestat);
- X if (filestat.st_size > 1024)
- X *tcbufptr = saferealloc(*tcbufptr,(MEM_SIZE)filestat.st_size);
- X if (filestat.st_size) {
- X read(initfd,*tcbufptr,(int)filestat.st_size);
- X (*tcbufptr)[filestat.st_size-1] = '\0';
- X /* wipe out last newline */
- X sw_list(*tcbufptr);
- X }
- X else
- X **tcbufptr = '\0';
- X close(initfd);
- X }
- X else {
- X if (bleat)
- X printf(cantopen,*tcbufptr) FLUSH;
- X **tcbufptr = '\0';
- X }
- X}
- X
- X/* decode a list of space separated switches */
- X
- Xvoid
- Xsw_list(swlist)
- Xchar *swlist;
- X{
- X char *tmplist = safemalloc((MEM_SIZE) strlen(swlist) + 2);
- X /* semi-automatic string */
- X register char *p, inquote = 0;
- X
- X strcpy(tmplist,swlist);
- X for (p=tmplist; isspace(*p); p++) ; /* skip any initial spaces */
- X while (*p) { /* "String, or nothing" */
- X if (!inquote && isspace(*p)) { /* word delimiter? */
- X *p++ = '\0'; /* chop here */
- X while (isspace(*p)) /* these will be ignored later */
- X p++;
- X }
- X else if (inquote == *p) {
- X strcpy(p,p+1); /* delete trailing quote */
- X inquote = 0; /* no longer quoting */
- X }
- X else if (!inquote && *p == '"' || *p == '\'') {
- X /* OK, I know when I am not wanted */
- X inquote = *p; /* remember single or double */
- X strcpy(p,p+1); /* delete the quote */
- X } /* (crude, but effective) */
- X else if (*p == '\\') { /* quoted something? */
- X if (p[1] == '\n') /* newline? */
- X strcpy(p,p+2); /* "I didn't see anything" */
- X else {
- X strcpy(p,p+1); /* delete the backwhack */
- X p++; /* leave the whatever alone */
- X }
- X }
- X else
- X p++; /* normal char, leave it alone */
- X }
- X *++p = '\0'; /* put an extra null on the end */
- X if (inquote)
- X printf("Unmatched %c in switch\n",inquote) FLUSH;
- X for (p = tmplist; *p; /* p += strlen(p)+1 */ ) {
- X decode_switch(p);
- X while (*p++) ; /* point at null + 1 */
- X }
- X free(tmplist); /* this oughta be in Ada */
- X}
- X
- X/* decode a single switch */
- X
- Xvoid
- Xdecode_switch(s)
- Xregister char *s;
- X{
- X while (isspace(*s)) /* ignore leading spaces */
- X s++;
- X#ifdef DEBUGGING
- X if (debug)
- X printf("Switch: %s\n",s) FLUSH;
- X#endif
- X if (*s != '-' && *s != '+') { /* newsgroup pattern */
- X setngtodo(s);
- X }
- X else { /* normal switch */
- X bool upordown = *s == '-' ? TRUE : FALSE;
- X char tmpbuf[LBUFLEN];
- X
- X s++;
- X switch (*s) {
- X#ifdef TERMMOD
- X case '=': {
- X char *beg = s+1;
- X
- X while (*s && *s != '-' && *s != '+') s++;
- X cpytill(tmpbuf,beg,*s);
- X if (upordown ? strEQ(getenv("TERM"),tmpbuf)
- X : strNE(getenv("TERM"),tmpbuf) ) {
- X decode_switch(s);
- X }
- X break;
- X }
- X#endif
- X#ifdef BAUDMOD
- X case '0': case '1': case '2': case '3': case '4':
- X case '5': case '6': case '7': case '8': case '9':
- X if (upordown ? (just_a_sec*10 <= atoi(s))
- X : (just_a_sec*10 >= atoi(s)) ) {
- X while (isdigit(*s)) s++;
- X decode_switch(s);
- X }
- X break;
- X#endif
- X case '/':
- X if (checkflag)
- X break;
- X#ifdef SETENV
- X setenv("SAVEDIR", upordown ? "%p/%c" : "%p" );
- X setenv("SAVENAME", upordown ? "%a" : "%^C");
- X#else
- X notincl("-/");
- X#endif
- X break;
- X case 'c':
- X checkflag = upordown;
- X break;
- X case 'C':
- X s++;
- X if (*s == '=') s++;
- X docheckwhen = atoi(s);
- X break;
- X case 'd': {
- X if (checkflag)
- X break;
- X s++;
- X if (*s == '=') s++;
- X if (cwd) {
- X chdir(cwd);
- X free(cwd);
- X }
- X cwd = savestr(s);
- X break;
- X }
- X#ifdef DEBUGGING
- X case 'D':
- X s++;
- X if (*s == '=') s++;
- X if (*s)
- X if (upordown)
- X debug |= atoi(s);
- X else
- X debug &= ~atoi(s);
- X else
- X if (upordown)
- X debug |= 1;
- X else
- X debug = 0;
- X break;
- X#endif
- X case 'e':
- X erase_screen = upordown;
- X break;
- X case 'E':
- X#ifdef SETENV
- X s++;
- X if (*s == '=')
- X s++;
- X strcpy(tmpbuf,s);
- X s = index(tmpbuf,'=');
- X if (s) {
- X *s++ = '\0';
- X setenv(tmpbuf,s);
- X }
- X else
- X setenv(tmpbuf,nullstr);
- X#else
- X notincl("-E");
- X#endif
- X break;
- X case 'F':
- X s++;
- X indstr = savestr(s);
- X break;
- X#ifdef INNERSEARCH
- X case 'g':
- X gline = atoi(s+1)-1;
- X break;
- X#endif
- X case 'H':
- X case 'h': {
- X register int len, i;
- X char *t;
- X int flag = (*s == 'h' ? HT_HIDE : HT_MAGIC);
- X
- X if (checkflag)
- X break;
- X s++;
- X len = strlen(s);
- X for (t=s; *t; t++)
- X if (isupper(*t))
- X *t = tolower(*t);
- X for (i=HEAD_FIRST; i<HEAD_LAST; i++)
- X if (!len || strnEQ(s,htype[i].ht_name,len))
- X if (upordown)
- X htype[i].ht_flags |= flag;
- X else
- X htype[i].ht_flags &= ~flag;
- X break;
- X }
- X case 'i':
- X s++;
- X if (*s == '=') s++;
- X initlines = atoi(s);
- X initlines_specified = TRUE;
- X break;
- X case 'l':
- X muck_up_clear = upordown;
- X break;
- X case 'L':
- X#ifdef CLEAREOL
- X can_home_clear = upordown;
- X#else
- X notincl("-L");
- X#endif
- X break;
- X case 'M':
- X mbox_always = upordown;
- X break;
- X case 'm':
- X s++;
- X if (*s == '=') s++;
- X if (!upordown)
- X marking = NOMARKING;
- X else if (*s == 'u')
- X marking = UNDERLINE;
- X else {
- X marking = STANDOUT;
- X }
- X break;
- X case 'N':
- X norm_always = upordown;
- X break;
- X#ifdef VERBOSE
- X case 'n':
- X fputs("This isn't readnews. Don't use -n.\n\n",stdout) FLUSH;
- X break;
- X#endif
- X case 'r':
- X findlast = upordown;
- X break;
- X case 's':
- X s++;
- X if (*s == '=') s++;
- X if (*s) {
- X countdown = atoi(s);
- X suppress_cn = FALSE;
- X }
- X else {
- X if (!upordown)
- X countdown = 5;
- X suppress_cn = upordown;
- X }
- X break;
- X case 'S':
- X#ifdef ARTSEARCH
- X s++;
- X if (*s == '=') s++;
- X if (*s)
- X scanon = atoi(s);
- X else
- X scanon = upordown*3;
- X#else
- X notincl("-S");
- X#endif
- X break;
- X case 't':
- X#ifdef VERBOSE
- X#ifdef TERSE
- X verbose = !upordown;
- X#else
- X notincl("+t");
- X#endif
- X#else
- X notincl("+t");
- X#endif
- X break;
- X case 'T':
- X typeahead = upordown;
- X break;
- X case 'v':
- X#ifdef VERIFY
- X verify = upordown;
- X#else
- X notincl("-v");
- X#endif
- X break;
- X case 'x':
- X#ifdef USETHREADS
- X s++;
- X if (*s == '=') s++;
- X if (*s <= '9' && *s >= '0') {
- X if ((max_tree_lines = atoi(s)) > 11)
- X max_tree_lines = 11;
- X do {
- X s++;
- X } while (*s <= '9' && *s >= '0');
- X } else
- X max_tree_lines = upordown*6;
- X if (*s)
- X strncpy(select_order, s, 3);
- X if (mode == 'i')
- X use_threads = upordown;
- X else if (use_threads != upordown)
- X printf("You must exit and restart to turn threaded operation %s.\n\n",
- X upordown ? "on" : "off");
- X#else
- X notincl("-x");
- X#endif
- X break;
- X case 'X':
- X#ifdef USETHREADS
- X s++;
- X if (*s == '=') s++;
- X if (*s <= '9' && *s >= '0') {
- X select_on = atoi(s);
- X do {
- X s++;
- X } while (*s <= '9' && *s >= '0');
- X } else
- X select_on = upordown;
- X if (*s)
- X end_select = *s++;
- X if (*s)
- X page_select = *s;
- X#else
- X notincl("-X");
- X#endif
- X break;
- X /*
- X * People want a way to avoid checking for new newsgroups on startup.
- X */
- X case 'q':
- X quickstart = upordown;
- X break;
- X default:
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\nIgnoring unrecognized switch: -%c\n", *s) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("\nIgnoring -%c\n", *s) FLUSH;
- X#endif
- X break;
- X }
- X }
- X}
- X
- X/* print current switch values */
- X
- Xvoid
- Xpr_switches()
- X{
- X static char mp[2] = {'+','-'};
- X register int i;
- X
- X fputs("\nCurrent switch settings:\n",stdout);
- X printf("%c/ ", mp[strEQ(getval("SAVEDIR",SAVEDIR),"%p/%c")]);
- X printf("%cc ", mp[checkflag]);
- X printf("-C%d ", docheckwhen);
- X printf("-d%s ", cwd);
- X#ifdef DEBUGGING
- X if (debug)
- X printf("-D%d ", debug);
- X#endif
- X printf("%ce ", mp[erase_screen]);
- X printf("-F\"%s\" ", indstr);
- X#ifdef INNERSEARCH
- X printf("-g%d", gline);
- X#endif
- X putchar('\n');
- X#ifdef VERBOSE
- X if (verbose) {
- X for (i=HEAD_FIRST; i<HEAD_LAST; i++)
- X printf("%ch%s%c",
- X mp[htype[i].ht_flags & HT_HIDE], htype[i].ht_name,
- X (! (i % 5) ? '\n' : ' ') );
- X }
- X#endif
- X printf("-i%d ", initlines);
- X printf("%cl ", mp[muck_up_clear]);
- X#ifdef CLEAREOL
- X printf("%cL ", mp[can_home_clear]);
- X#endif /* CLEAREOL */
- X if (marking)
- X printf("-m%c ",marking==UNDERLINE?'u':'s');
- X else
- X printf("+m ");
- X printf("%cM ", mp[mbox_always]);
- X printf("%cN ", mp[norm_always]);
- X printf("%cr ", mp[findlast]);
- X if (countdown)
- X printf("-s%d ", countdown);
- X else
- X printf("%cs ", mp[suppress_cn]);
- X#ifdef ARTSEARCH
- X if (scanon)
- X printf("-S%d ",scanon);
- X else
- X printf("+S ");
- X#endif
- X#ifdef VERBOSE
- X#ifdef TERSE
- X printf("%ct ", mp[!verbose]);
- X#endif
- X#endif
- X printf("%cT ", mp[typeahead]);
- X#ifdef VERIFY
- X printf("%cv ", mp[verify]);
- X#endif
- X#ifdef USETHREADS
- X if (use_threads)
- X printf("-x%d%s ",max_tree_lines,select_order);
- X else
- X printf("+x ");
- X if (select_on)
- X printf("-X%d%c%c ",select_on,end_select,page_select);
- X else
- X printf("+X ");
- X#endif
- X fputs("\n\n",stdout) FLUSH;
- X#ifdef ONLY
- X if (maxngtodo) {
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("Current restriction:",stdout);
- X ELSE
- X#endif
- X#ifdef TERSE
- X fputs("Only:",stdout);
- X#endif
- X for (i=0; i<maxngtodo; i++)
- X printf(" %s",ngtodo[i]);
- X fputs("\n\n",stdout) FLUSH;
- X }
- X#ifdef VERBOSE
- X else if (verbose)
- X fputs("No restriction.\n\n",stdout) FLUSH;
- X#endif
- X#endif
- X}
- X
- Xvoid
- Xcwd_check()
- X{
- X char tmpbuf[LBUFLEN];
- X
- X if (!cwd)
- X cwd = savestr(filexp("~/News"));
- X strcpy(tmpbuf,cwd);
- X if (chdir(cwd)) {
- X safecpy(tmpbuf,filexp(cwd),sizeof tmpbuf);
- X if (makedir(tmpbuf,MD_DIR) < 0 || chdir(tmpbuf) < 0) {
- X interp(cmd_buf, (sizeof cmd_buf), "%~/News");
- X if (makedir(cmd_buf,MD_DIR) < 0)
- X strcpy(tmpbuf,homedir);
- X else
- X strcpy(tmpbuf,cmd_buf);
- X chdir(tmpbuf);
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\
- XCannot make directory %s--\n\
- X articles will be saved to %s\n\
- X\n\
- X",cwd,tmpbuf) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("\
- XCan't make %s--\n\
- X using %s\n\
- X\n\
- X",cwd,tmpbuf) FLUSH;
- X#endif
- X }
- X }
- X free(cwd);
- X getwd(tmpbuf);
- X if (eaccess(tmpbuf,2)) {
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\
- XCurrent directory %s is not writeable--\n\
- X articles will be saved to home directory\n\n\
- X",tmpbuf) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("%s not writeable--using ~\n\n",tmpbuf) FLUSH;
- X#endif
- X strcpy(tmpbuf,homedir);
- X }
- X cwd = savestr(tmpbuf);
- X}
- END_OF_FILE
- if test 11791 -ne `wc -c <'sw.c'`; then
- echo shar: \"'sw.c'\" unpacked with wrong size!
- fi
- # end of 'sw.c'
- fi
- echo shar: End of archive 10 \(of 14\).
- cp /dev/null ark10isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 14 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
-